﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Collections;
using System.Runtime.InteropServices;
using System.IO;
using System.Drawing.Imaging;
using Microsoft.Win32;
using System.Drawing.Drawing2D;
using System.Diagnostics;
using System.Reflection;
using LogLib;
using ComLib.ComFun;
using ComLib.ComType;

namespace ComLib.ComFun
{
    public delegate bool CallBack(IntPtr hwnd, int lParam);
    public delegate void FillEnabledStringDelegate(string baseStr, bool enabled);
    public delegate void FillFieldValueStringDelegate(string field, object value);

    public class IPCCom
    {
        public static ImageFormat GetImageFormat(ImageFormats format)
        {
            switch (format)
            {
                case ImageFormats.Bmp:
                    return ImageFormat.Bmp;
                case ImageFormats.Png:
                    return ImageFormat.Png;
                case ImageFormats.Jpeg:
                    return ImageFormat.Jpeg;
                default:
                    return ImageFormat.Bmp;
            }
        }

        public static List<string> ReadTextLines(string filePath)
        {
            if (!File.Exists(filePath))
                return null;
            List<string> list = new List<string>();          
            using (StreamReader stream = new StreamReader(filePath, Encoding.Unicode))
            {
                string str;
                while ((str = stream.ReadLine()) != null)
                {
                    list.Add(str);
                }
            }
            return list;
        }

        public static List<Type> GetConfigClasses(string nameSpace)
        {
            List<Type> listTypes = new List<Type>();
            Assembly asm = Assembly.GetExecutingAssembly();
            foreach (Type type in asm.GetTypes())
            {
                if (type.Namespace == nameSpace)
                {
                    listTypes.Add(type);
                }
            }
            return listTypes;
        }

        public static bool IsProcessExist(string strProcessName)
        {
            Process[] prc = Process.GetProcesses();
            foreach (Process pr in prc) //遍历整个进程
            {
                if (pr.ProcessName.Contains(strProcessName)) //如果进程存在
                {
                    return true;
                }
            }
            return false;
        }

        //将Byte转换为结构体类型
        public static byte[] StructToBytes(object structObj)
        {
            int size = Marshal.SizeOf(structObj);
            byte[] bytes = new byte[size];
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //将结构体拷到分配好的内存空间
            Marshal.StructureToPtr(structObj, structPtr, false);
            //从内存空间拷贝到byte 数组
            Marshal.Copy(structPtr, bytes, 0, size);
            //释放内存空间
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

        public static string GetApplyString(ApplyTo v)
        {
            switch (v)
            {
                case ApplyTo.ExitAndEntry:
                    return "出入境证件";
                case ApplyTo.IDCard:
                     return "身份证";
                case ApplyTo.PortVisa:
                      return "机场口岸签证";
                case ApplyTo.SocialSecurity:
                      return "社保制证";
                default:
                      return "出入境证件";
            }
        }

        public static void ShutDown()
        {
            Process p = new Process();
            p.StartInfo.FileName = "shutdown.exe";
            p.StartInfo.Arguments = "-s -t 0";
            p.Start();
        }

        public static void ShutDownQuickly()
        {
            Process p = new Process();
            p.StartInfo.FileName = "shutdown.exe";
            p.StartInfo.Arguments = "-s -f -t 0";
            p.Start();
        }

        public static void SetImageResolution(string src, string dest, float xp, float yp)
        {
            Bitmap source = new Bitmap(src);
            Bitmap img2 = new Bitmap(source.Width, source.Height, PixelFormat.Format24bppRgb);
            img2.SetResolution(xp, yp);
            using (Graphics g = Graphics.FromImage(img2))
            {
                g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
                g.DrawImage(source, new Rectangle(0, 0, img2.Width, img2.Height), 0, 0, source.Width, source.Height, GraphicsUnit.Pixel);
                g.Dispose();
                img2.Save(dest, ImageFormat.Jpeg);
            }
            source.Dispose();
            img2.Dispose();
            source = null;
            img2 = null;
        }

        public static void KillProcess(string processName)
        {
            Process[] p = Process.GetProcessesByName(processName);
            for (int i = 0; i < p.Length; i++)
            {
                p[i].CloseMainWindow();
                p[i].Kill();
            }             
        }

        public static void Reboot()
        {
            Process p = new Process();
            p.StartInfo.FileName = "shutdown.exe";
            p.StartInfo.Arguments = "-r -t 0";
            p.Start();
        }

        public static byte[] ReadByteArray(string strFilePath)
        {
            using (FileStream stream = new FileInfo(strFilePath).OpenRead())
            {
                byte[] buffer = new Byte[stream.Length];
                stream.Read(buffer, 0, Convert.ToInt32(stream.Length));
                stream.Close();
                return buffer;
            }
        }
        public static void ByteToDat(byte[] bData, int nDataLength, string strTplFilePatch)
        {
            try
            {
                MemoryStream m = new MemoryStream(bData, 0, nDataLength);

                //将指纹模板文件放在当前目录下，保存为e.wav；当然如果是图片，可以保存为a.jpg
                FileStream fs = new FileStream(strTplFilePatch, FileMode.CreateNew);
                m.WriteTo(fs);
                m.Close();
                fs.Close();
                m = null;
                fs = null;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static byte[] Bitmap2ByteArray(Bitmap img)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                img.Save(stream, ImageFormat.Jpeg);
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }

        public static byte[] Bitmap2ByteArray_BMP(Bitmap img)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                img.Save(stream, ImageFormat.Bmp);
                byte[] data = new byte[stream.Length];
                stream.Seek(0, SeekOrigin.Begin);
                stream.Read(data, 0, Convert.ToInt32(stream.Length));
                return data;
            }
        }

        public static Bitmap BytesToBitmap(byte[] Bytes)
        {
            MemoryStream stream = null;
            try
            {
                stream = new MemoryStream(Bytes);
                return new Bitmap(stream);
            }
            catch (ArgumentNullException ex)
            {
                throw ex;
            }
            catch (ArgumentException ex)
            {
                throw ex;
            }
            finally
            {
                stream.Close();
            }
        }

        /// <summary>
        /// Resize图片
        /// </summary>
        /// <param name="bmp">原始Bitmap</param>
        /// <param name="newW">新的宽度</param>
        /// <param name="newH">新的高度</param>
        /// <param name="Mode">保留着，暂时未用</param>
        /// <returns>处理以后的图片</returns>
        public static Bitmap ResizeImage(Bitmap bmp, int newW, int newH, int Mode)
        {
            if (bmp == null)
            {
                return null;
            }
            try
            {
                Bitmap b = new Bitmap(newW, newH);
                using (Graphics g = Graphics.FromImage(b))
                {
                    // 插值算法的质量
                    g.InterpolationMode = InterpolationMode.HighQualityBicubic;
                    g.DrawImage(bmp, new Rectangle(0, 0, newW, newH), new Rectangle(0, 0, bmp.Width, bmp.Height), GraphicsUnit.Pixel);
                }    
                return b;
            }
            catch(Exception ex)
            {
                Log.WriteException(ex.ToString());
                return null;
            }
        }

        /// <summary>  
        /// 剪裁 -- 用GDI+   
        /// </summary>  
        /// <param name="b">原始Bitmap</param>       
        /// <param name="recArea">剪裁区域</param>
        /// <returns>剪裁后的Bitmap</returns>  
        public static Bitmap Cut(Bitmap b, Rectangle recArea)
        {
            if (b == null)
            {
                return null;
            }
            int w = b.Width;
            int h = b.Height;
            if (recArea.X >= w || recArea.Y >= h)
            {
                return null;
            }
            if (recArea.X + recArea.Width > w)
            {
                recArea.Width = w - recArea.X;
            }
            if (recArea.Y + recArea.Height > h)
            {
                recArea.Height = h - recArea.Y;
            }
            try
            {
                Bitmap bmpOut = new Bitmap(recArea.Width, recArea.Height, PixelFormat.Format24bppRgb);
                using (Graphics g = Graphics.FromImage(bmpOut))
                {
                    g.DrawImage(b, new Rectangle(0, 0, recArea.Width, recArea.Height), new Rectangle(recArea.X, recArea.Y, recArea.Width, recArea.Height), GraphicsUnit.Pixel);
                }                  
                return bmpOut;
            }
            catch(Exception ex)
            {
                Log.WriteException(ex.ToString());
                return null;
            }
        }
       
        public static string OSName()
        {
            RegistryKey rk;
            rk = Registry.LocalMachine.OpenSubKey("Software\\Microsoft\\Windows NT\\CurrentVersion");
            string OSname = rk.GetValue("ProductName").ToString();//产品名称（系统名称）
            string buildNumber = rk.GetValue("CurrentBuildNumber").ToString();//系统版本号
            rk.Close();
            return OSname;
        }
        public static bool IsInDebugMode(string FileName)
        {
            var assembly = System.Reflection.Assembly.LoadFile(FileName);
            var attributes = assembly.GetCustomAttributes(typeof(System.Diagnostics.DebuggableAttribute), false);
            if (attributes.Length > 0)
            {
                var debuggable = attributes[0] as System.Diagnostics.DebuggableAttribute;
                if (debuggable != null)
                    return (debuggable.DebuggingFlags & System.Diagnostics.DebuggableAttribute.DebuggingModes.Default) == System.Diagnostics.DebuggableAttribute.DebuggingModes.Default;
                else
                    return false;
            }
            else
                return false;
        }
        public static double colorDistance(int rgb1, int rgb2)
        {
            int r1 = rgb1 >> 16 & 0xFF;
            int g1 = rgb1 >> 8 & 0xFF;
            int b1 = rgb1 & 0xFF;

            int r2 = rgb2 >> 16 & 0xFF;
            int g2 = rgb2 >> 8 & 0xFF;
            int b2 = rgb2 & 0xFF;

            return Math.Sqrt((r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) + (b1 - b2) * (b1 - b2));
        }

        public static void processBrightness(ref Bitmap image, double brightness)
        {
            double l_brightness = brightness;

            for (int x = 0; x < image.Width; x++)
            {
                for (int y = 0; y < image.Height; y++)
                {
                    int rgb = image.GetPixel(x, y).ToArgb();

                    double r = rgb >> 16 & 0xFF;
                    double g = rgb >> 8 & 0xFF;
                    double b = rgb & 0xFF;

                    r += (1.0D - r / 255.0D) * l_brightness;
                    g += (1.0D - g / 255.0D) * l_brightness;
                    b += (1.0D - b / 255.0D) * l_brightness;

                    if (r < 0.0D)
                        r = 0.0D;
                    if (r > 255.0D)
                        r = 255.0D;
                    if (g < 0.0D)
                        g = 0.0D;
                    if (g > 255.0D)
                        g = 255.0D;
                    if (b < 0.0D)
                        b = 0.0D;
                    if (b > 255.0D)
                    {
                        b = 255.0D;
                    }
                    Color color = Color.FromArgb((int)r, (int)g, (int)b);
                    image.SetPixel(x, y, color);
                }

            }
        }

        public static void processContrast(ref Bitmap image, double contrast)
        {
            double l_contrast = contrast;
            l_contrast = Math.Pow((127.0D + l_contrast) / 127.0D, 2.0D);

            for (int x = 0; x < image.Width; x++)
                for (int y = 0; y < image.Width; y++)
                {
                    int rgb = image.GetPixel(x, y).ToArgb();
                    double r = rgb >> 16 & 0xFF;
                    double g = rgb >> 8 & 0xFF;
                    double b = rgb & 0xFF;

                    r /= 255.0D;
                    r -= 0.5D;
                    r *= l_contrast;
                    r += 0.5D;
                    r *= 255.0D;

                    g /= 255.0D;
                    g -= 0.5D;
                    g *= l_contrast;
                    g += 0.5D;
                    g *= 255.0D;

                    b /= 255.0D;
                    b -= 0.5D;
                    b *= l_contrast;
                    b += 0.5D;
                    b *= 255.0D;

                    if (r < 0.0D)
                        r = 0.0D;
                    if (r > 255.0D)
                        r = 255.0D;
                    if (g < 0.0D)
                        g = 0.0D;
                    if (g > 255.0D)
                        g = 255.0D;
                    if (b < 0.0D)
                        b = 0.0D;
                    if (b > 255.0D)
                    {
                        b = 255.0D;
                    }
                    //imageOut.setRGB(x, y, (int)r << 16 | (int)g << 8 |(int)b);
                    Color color = Color.FromArgb((int)r, (int)g, (int)b);
                    image.SetPixel(x, y, color);
                }
        }

        public static int eraseBackground(ref Bitmap src, int x, int y, int newColor, int threshold, bool replace)
        {
            int width = src.Width;
            int height = src.Height;
            int[,] bmap = new int[width, height];
            int seek = src.GetPixel(x, y).ToArgb();

            Stack stack = new Stack();
            stack.Push(new Point(x, y));
            //while (!stack.isEmpty) {
            //  floodFillPix(seek, threshold, src, bmap, stack);
            //}
            while (stack.Count > 0)
            {
                floodFillPix(seek, threshold, src, bmap, ref stack);
            }
            floodFillSinglePix(bmap);

            int gray = 0; int count = 0;
            for (int i = 0; i < width; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    if (bmap[i, j] == 1)
                    {
                        gray += toGray(src.GetPixel(i, j).ToArgb());
                        count++;
                        if (replace)
                        {
                            Color color = Color.FromArgb(newColor);
                            src.SetPixel(i, j, color);
                        }
                    }
                }
            }
            return gray / (count == 0 ? 1 : count);
        }

        private static void floodFillPix(int seek, double dis, Bitmap src, int[,] bmap, ref Stack stack)
        {
            Point p = (Point)stack.Pop();
            int x = p.X; int y = p.Y;
            int old = src.GetPixel(x, y).ToArgb();

            if ((x - 1 >= 0) &&
              (bmap[(x - 1), y] == 0))
            {
                if (condition(old, src.GetPixel(x - 1, y).ToArgb(), dis))
                {
                    bmap[(x - 1), y] = 1;
                    stack.Push(new Point(x - 1, y));
                }
                else
                {
                    bmap[(x - 1), y] = 2;
                }
            }

            if (((x + 1 < src.Width)) &&
              (bmap[(x + 1), y] == 0))
            {
                if (condition(old, src.GetPixel(x + 1, y).ToArgb(), dis))
                {
                    bmap[(x + 1), y] = 1;
                    stack.Push(new Point(x + 1, y));
                }
                else
                {
                    bmap[(x + 1), y] = 2;
                }
            }

            if ((y - 1 >= 0) &&
              (bmap[x, (y - 1)] == 0))
            {
                if (condition(old, src.GetPixel(x, y - 1).ToArgb(), dis))
                {
                    bmap[x, (y - 1)] = 1;
                    stack.Push(new Point(x, y - 1));
                }
                else
                {
                    bmap[x, (y - 1)] = 2;
                }
            }

            if ((y + 1 < src.Height) &&
              (bmap[x, (y + 1)] == 0))
                if (condition(old, src.GetPixel(x, y + 1).ToArgb(), dis))
                {
                    bmap[x, (y + 1)] = 1;
                    stack.Push(new Point(x, y + 1));
                }
                else
                {
                    bmap[x, (y + 1)] = 2;
                }
        }

        public static int toGray(int rgb)
        {
            int b = (rgb & 0xFF) >> 0;
            int g = (rgb & 0xFF00) >> 8;
            int r = (rgb & 0xFF0000) >> 16;
            return (r * 299 + g * 587 + b * 114 + 500) / 1000;
        }

        private static bool condition(int r1, int r2, double dis)
        {
            return (colorDistance(r1, r2) < dis) && (!isHuman(r2));
        }

        public static bool isHuman(int rgb)
        {
            int r = rgb >> 16 & 0xFF;
            int g = rgb >> 8 & 0xFF;
            int b = rgb & 0xFF;

            int max = Math.Max(r, Math.Max(g, b));
            int min = Math.Min(r, Math.Min(g, b));
            int rg = Math.Abs(r - g);
            if ((r > 95) && (g > 40) && (b > 20) && (rg > 15) && (max - min > 15) && (r > g) && (r > b))
            {
                return true;
            }
            return false;

        }
        private static void floodFillSinglePix(int[,] bmap)
        {
            int sum = 0;
            for (int i = 0; i < bmap.GetLength(0); i++)
                for (int j = 0; j < bmap.GetLength(1); j++)
                {
                    sum = 0;
                    if (bmap[i, j] == 2)
                    {
                        int x = i;
                        int y = j - 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i - 1;
                        y = j - 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i - 1;
                        y = j;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i - 1;
                        y = j + 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i;
                        y = j + 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i + 1;
                        y = j + 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i + 1;
                        y = j;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i + 1;
                        y = j - 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i;
                        y = j - 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }

                        x = i - 1;
                        y = j - 1;
                        if ((x >= 0) && (x < bmap.GetLength(0)) && (y >= 0) &&
                          (y < bmap.GetLength(1)))
                        {
                            if ((bmap[x, y] == 0) || (bmap[x, y] == 2))
                                sum++;
                            else
                            {
                                sum = 0;
                            }
                        }
                        if (sum < 3)
                        {
                            bmap[i, j] = 1;
                        }
                    }
                }
        }
    }
}
